
/**
 * @file main
 *
 */

/*********************
 *      INCLUDES
 *********************/
#define _DEFAULT_SOURCE /* needed for usleep() */
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include "lv_drv_conf.h"
#include "lvgl/lvgl.h"
#include "lvgl/examples/lv_examples.h"
#include "lvgl/demos/lv_demos.h"
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include "sc.h"
#include "btn_event.h"
#include "client.h"
#include "bq.h"

#if USE_SDL
  #define SDL_MAIN_HANDLED /*To fix SDL's "undefined reference to WinMain" issue*/
  #include <SDL2/SDL.h>
  #include "lv_drivers/sdl/sdl.h"
#elif USE_X11
  #include "lv_drivers/x11/x11.h"
#endif
// #include "lv_drivers/display/monitor.h"
// #include "lv_drivers/indev/mouse.h"
// #include "lv_drivers/indev/keyboard.h"
// #include "lv_drivers/indev/mousewheel.h"

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/
static void hal_init(void);
static void hal_deinit(void);
static void* tick_thread(void *data);

/**********************
 *  STATIC VARIABLES
 **********************/
static pthread_t thr_tick;    /* thread */
static bool end_tick = false; /* flag to terminate thread */

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *      VARIABLES
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/
#if 0
static void user_image_demo()
{
  lv_obj_t * img = lv_gif_create(lv_scr_act());
  lv_gif_set_src(img, "A:lvgl/examples/libs/gif/bulb.gif");
  lv_obj_align(img, LV_ALIGN_BOTTOM_RIGHT, -20, -20);

  lv_color_t bg_color = lv_palette_lighten(LV_PALETTE_LIGHT_BLUE, 5);
    lv_color_t fg_color = lv_palette_darken(LV_PALETTE_BLUE, 4);

    lv_obj_t * qr = lv_qrcode_create(lv_scr_act(), 150, fg_color, bg_color);

    /*Set data*/
    const char * data = "https://lvgl.io";
    lv_qrcode_update(qr, data, strlen(data));
    lv_obj_center(qr);

    /*Add a border with bg_color*/
    lv_obj_set_style_border_color(qr, bg_color, 0);
    lv_obj_set_style_border_width(qr, 5, 0);

    /*Create a font*/
    static lv_ft_info_t info;
    /*FreeType uses C standard file system, so no driver letter is required.*/
    info.name = "./lvgl/examples/libs/freetype/Lato-Regular.ttf";
    info.weight = 24;
    info.style = FT_FONT_STYLE_NORMAL;
    info.mem = NULL;
    if(!lv_ft_font_init(&info)) {
        LV_LOG_ERROR("create failed.");
    }

    /*Create style with the new font*/
    static lv_style_t style;
    lv_style_init(&style);
    lv_style_set_text_font(&style, info.font);
    lv_style_set_text_align(&style, LV_TEXT_ALIGN_CENTER);

    /*Create a label with the new style*/
    lv_obj_t * label = lv_label_create(lv_scr_act());
    lv_obj_add_style(label, &style, 0);
    lv_label_set_text(label, "Hello world\nI'm a font created with FreeType");
    lv_obj_set_pos(label, 10, 10);

    lv_obj_t *  img1 = lv_img_create(lv_scr_act());
    /* Assuming a File system is attached to letter 'A'
     * E.g. set LV_USE_FS_STDIO 'A' in lv_conf.h */
    lv_img_set_src(img1, "A:lvgl/examples/libs/png/wink.png");
    lv_obj_align(img1, LV_ALIGN_LEFT_MID, 20, 0);

    lv_obj_t * wp;

    wp = lv_img_create(lv_scr_act());
    /* Assuming a File system is attached to letter 'A'
     * E.g. set LV_USE_FS_STDIO 'A' in lv_conf.h */
    lv_img_set_src(wp, "A:lvgl/examples/libs/sjpg/small_image.sjpg");
    lv_obj_align(wp, LV_ALIGN_RIGHT_MID, -20, 0);

    lv_obj_t * img2 = lv_img_create(lv_scr_act());
    /* Assuming a File system is attached to letter 'A'
     * E.g. set LV_USE_FS_STDIO 'A' in lv_conf.h */
    lv_img_set_src(img2, "A:lvgl/examples/libs/sjpg/lv_example_jpg.jpg");
    //lv_obj_center(img);
    lv_obj_align(img2, LV_ALIGN_TOP_RIGHT, -20, 20);

    lv_obj_t * img3 = lv_img_create(lv_scr_act());
    /* Assuming a File system is attached to letter 'A'
     * E.g. set LV_USE_FS_STDIO 'A' in lv_conf.h */
#if LV_COLOR_DEPTH == 32
    lv_img_set_src(img3, "A:lvgl/examples/libs/bmp/example_32bit.bmp");
#elif LV_COLOR_DEPTH == 16
    lv_img_set_src(img, "A:lvgl/examples/libs/bmp/example_16bit.bmp");
#endif
    lv_obj_align(img3, LV_ALIGN_BOTTOM_MID, 0, -20);

    lv_obj_t * img4 = lv_img_create(lv_scr_act());
    lv_img_set_src(img4, "A:lvgl/examples/libs/ffmpeg/ffmpeg.png");
    lv_obj_align(img4, LV_ALIGN_BOTTOM_LEFT, 20, -20);

    lv_obj_t * player = lv_ffmpeg_player_create(lv_scr_act());
    lv_ffmpeg_player_set_src(player, "./lvgl/examples/libs/ffmpeg/birds.mp4");
    lv_ffmpeg_player_set_auto_restart(player, true);
    lv_ffmpeg_player_set_cmd(player, LV_FFMPEG_PLAYER_CMD_START);
    lv_obj_align(player, LV_ALIGN_TOP_MID, 0, 20);
}
#endif

lv_obj_t *scr3;
lv_obj_t *scr2;
lv_obj_t *scr1;
lv_obj_t* img;
int ret;
char account[50];
char password[50];
lv_obj_t* ta1;
lv_obj_t* ta2;
lv_obj_t* ta3;
lv_obj_t* ta4;
lv_obj_t * ta5;
lv_obj_t * ta6;
lv_obj_t * mbox3;
char sendbuf[1024];//发送给服务器的信息
char recvbuf[1024];//接收服务器的返回信息
lv_obj_t * btn;//列表按钮
struct clientlist *clienthead;//客户端链表头节点
lv_obj_t * list;//列表
static lv_style_t rightstyle;

int main(int argc, char **argv)
{
	/*Initialize LVGL*/
	lv_init(); //初始化LVGL  

	/*Initialize the HAL (display, input devices, tick) for LVGL*/
	hal_init(); //初始化液晶屏，输入设备(键盘,触摸屏，鼠标)

  clienthead=list_init();

  //创建一个界面，这个界面是用户登录界面，有登录按钮和注册按钮
  scr1 = lv_obj_create(lv_scr_act());
  //设置界面大小
  lv_obj_set_size(scr1, 800, 480);
  //把界面放到屏幕中央
  lv_obj_center(scr1);

  //设置背景图片
  img = lv_img_create(scr1);
  //声明图片
  LV_IMG_DECLARE(lover);
  lv_img_set_src(img, &lover);
  lv_obj_align(img, LV_ALIGN_CENTER, 0, 0);
  
  //创建登录按钮
  lv_obj_t* bt1 = lv_btn_create(img);
  //创建注册按钮
  lv_obj_t* bt2 = lv_btn_create(img);
  //将登录按钮放到界面的左下角
  lv_obj_align(bt1, LV_ALIGN_BOTTOM_LEFT, 200, -20);
  //将注册按钮放到界面的右下角
  lv_obj_align(bt2, LV_ALIGN_BOTTOM_RIGHT, -200, -20);
  //设置登录按钮的大小
  lv_obj_set_size(bt1, 100, 50);
  //给登录按钮设置文本
  lv_obj_t* label1 = lv_label_create(bt1);
  lv_obj_set_style_text_color(label1, lv_color_hex(0xf4a13e),0);
  show_chinese(22,label1);
  lv_label_set_text(label1, "登录");
  //设置注册按钮的大小
  lv_obj_set_size(bt2, 100, 50);
  //给注册按钮设置文本
  lv_obj_t* label2 = lv_label_create(bt2);
  show_chinese(22,label2);
  lv_label_set_text(label2, "注册");
  lv_obj_set_style_text_color(label2, lv_color_hex(0xf4a13e),0);
  //给登录按钮绑定一个事件响应函数，判断账号密码是否正确
  //如果正确，则刷新界面跳转到聊天页面，否则弹出提示框提示账号密码错误
  lv_obj_add_event_cb(bt1, bt1_cb, LV_EVENT_CLICKED, NULL);
  //给注册按钮绑定一个事件响应函数，跳转到注册页面
  lv_obj_add_event_cb(bt2, bt2_cb, LV_EVENT_CLICKED, NULL);

  //创建标签，用来显示这是登录界面
  lv_obj_t* label = lv_label_create(img);
  //将标签放到界面中间偏上的位置
  lv_obj_align(label, LV_ALIGN_CENTER, 0, -100);
  //设置标签的文本
  lv_label_set_text(label, "This is login page");
  //设置标签的大小
  lv_obj_set_size(label, 200, 200);
  //设置标签的字体大小
  //show_chinese(18,label);

  //创建账号的输入框
  ta1 = lv_textarea_create(img);
  //将账号输入框放到界面中间偏上的位置  
  lv_obj_align(ta1, LV_ALIGN_CENTER, 0, -50);
  //设置账号输入框的大小
  lv_obj_set_size(ta1, 300, 50);
  //设置账号输入框的提示文本
  lv_textarea_set_placeholder_text(ta1, "Please enter your account");
  //在账号输入框左侧加入一个标签，标签上的文字是“账号：”
  lv_obj_t* label3 = lv_label_create(img);
  lv_label_set_text(label3, "Account:");
  lv_obj_align(label3, LV_ALIGN_CENTER, -200, -50);

  //创建密码的输入框
  ta2 = lv_textarea_create(img);
  //将密码输入框放到界面中间的位置
  lv_obj_align(ta2, LV_ALIGN_CENTER, 0, 50);
  //设置密码输入框的大小
  lv_obj_set_size(ta2, 300, 50);
  //设置密码输入框的提示文本
  lv_textarea_set_placeholder_text(ta2, "Please enter your password");
  //在密码输入框左侧加入一个标签，标签上的文字是“密码：”
  lv_obj_t* label4 = lv_label_create(img);
  lv_label_set_text(label4, "Password:");
  lv_obj_align(label4, LV_ALIGN_CENTER, -200, 50);

  
  //表示客户端接收到了注册成功的信息，那就创建一个消息盒子，提示用户注册成功
  const char * btns[] = {"OK", ""};
	mbox3 = lv_msgbox_create(img,"Welcome","Close the window",btns,false);
  //将消息弹窗放到界面中间的位置
  lv_obj_align(mbox3, LV_ALIGN_CENTER, 0, 0);
  //给消息弹窗按钮设置点击事件
  lv_obj_add_event_cb(mbox3, mbox_event_cb, LV_EVENT_CLICKED, NULL);

  
	
	

	while(1) {
		//帮你刷新模拟器界面，当你拖动模拟器的时候，模拟器界面会在新的位置刷新
		//帮你检测界面中各个组件触发的事件
		lv_timer_handler();
		usleep(5 * 1000);
	}

	hal_deinit(); //关闭硬件
	return 0; 
}

/**********************
 *   STATIC FUNCTIONS
 **********************/

/**
 * Initialize the Hardware Abstraction Layer (HAL) for the LVGL graphics
 * library
 */
static void hal_init(void)
{
  /* mouse input device */
  static lv_indev_drv_t indev_drv_1;
  lv_indev_drv_init(&indev_drv_1);
  indev_drv_1.type = LV_INDEV_TYPE_POINTER;

  /* keyboard input device */
  static lv_indev_drv_t indev_drv_2;
  lv_indev_drv_init(&indev_drv_2);
  indev_drv_2.type = LV_INDEV_TYPE_KEYPAD;

  /* mouse scroll wheel input device */
  static lv_indev_drv_t indev_drv_3;
  lv_indev_drv_init(&indev_drv_3);
  indev_drv_3.type = LV_INDEV_TYPE_ENCODER;

  lv_group_t *g = lv_group_create();
  lv_group_set_default(g);

  lv_disp_t *disp = NULL;

#if USE_SDL
  /* Use the 'monitor' driver which creates window on PC's monitor to simulate a display*/
  sdl_init();

  /*Create a display buffer*/
  static lv_disp_draw_buf_t disp_buf1;
  static lv_color_t buf1_1[MONITOR_HOR_RES * 100];
  static lv_color_t buf1_2[MONITOR_HOR_RES * 100];
  lv_disp_draw_buf_init(&disp_buf1, buf1_1, buf1_2, MONITOR_HOR_RES * 100);

  /*Create a display*/
  static lv_disp_drv_t disp_drv;
  lv_disp_drv_init(&disp_drv); /*Basic initialization*/
  disp_drv.draw_buf = &disp_buf1;
  disp_drv.flush_cb = sdl_display_flush;
  disp_drv.hor_res = MONITOR_HOR_RES;
  disp_drv.ver_res = MONITOR_VER_RES;
  disp_drv.antialiasing = 1;

  disp = lv_disp_drv_register(&disp_drv);

  /* Add the input device driver */
  // mouse_init();
  indev_drv_1.read_cb = sdl_mouse_read;

  // keyboard_init();
  indev_drv_2.read_cb = sdl_keyboard_read;

  // mousewheel_init();
  indev_drv_3.read_cb = sdl_mousewheel_read;

#elif USE_X11
  lv_x11_init("LVGL Simulator Demo", DISP_HOR_RES, DISP_VER_RES);

  /*Create a display buffer*/
  static lv_disp_draw_buf_t disp_buf1;
  static lv_color_t buf1_1[DISP_HOR_RES * 100];
  static lv_color_t buf1_2[DISP_HOR_RES * 100];
  lv_disp_draw_buf_init(&disp_buf1, buf1_1, buf1_2, DISP_HOR_RES * 100);

  /*Create a display*/
  static lv_disp_drv_t disp_drv;
  lv_disp_drv_init(&disp_drv);
  disp_drv.draw_buf = &disp_buf1;
  disp_drv.flush_cb = lv_x11_flush;
  disp_drv.hor_res = DISP_HOR_RES;
  disp_drv.ver_res = DISP_VER_RES;
  disp_drv.antialiasing = 1;

  disp = lv_disp_drv_register(&disp_drv);

  /* Add the input device driver */
  indev_drv_1.read_cb = lv_x11_get_pointer;
  indev_drv_2.read_cb = lv_x11_get_keyboard;
  indev_drv_3.read_cb = lv_x11_get_mousewheel;
#endif
  /* Set diplay theme */
  lv_theme_t * th = lv_theme_default_init(disp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), LV_THEME_DEFAULT_DARK, LV_FONT_DEFAULT);
  lv_disp_set_theme(disp, th);

  /* Tick init */
  end_tick = false;
  pthread_create(&thr_tick, NULL, tick_thread, NULL);

  /* register input devices */
  lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);
  lv_indev_t *kb_indev = lv_indev_drv_register(&indev_drv_2);
  lv_indev_t *enc_indev = lv_indev_drv_register(&indev_drv_3);
  lv_indev_set_group(kb_indev, g);
  lv_indev_set_group(enc_indev, g);

  /* Set a cursor for the mouse */
  LV_IMG_DECLARE(mouse_cursor_icon);                   /*Declare the image file.*/
  lv_obj_t * cursor_obj = lv_img_create(lv_scr_act()); /*Create an image object for the cursor*/
  lv_img_set_src(cursor_obj, &mouse_cursor_icon);      /*Set the image source*/
  lv_indev_set_cursor(mouse_indev, cursor_obj);        /*Connect the image  object to the driver*/
}

/**
 * Releases the Hardware Abstraction Layer (HAL) for the LVGL graphics library
 */
static void hal_deinit(void)
{
  end_tick = true;
  pthread_join(thr_tick, NULL);

#if USE_SDL
  // nop
#elif USE_X11
  lv_x11_deinit();
#endif
}

/**
 * A task to measure the elapsed time for LVGL
 * @param data unused
 * @return never return
 */
static void* tick_thread(void *data) {
  (void)data;

  while(!end_tick) {
    usleep(5000);
    lv_tick_inc(5); /*Tell LittelvGL that 5 milliseconds were elapsed*/
  }

  return NULL;
}
